package com.glsc.ngateway.opmanage.service.outsys;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrDeptDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpDto;
import com.glsc.ngateway.common.api.ldap.feign.IFeignLdapService;
import com.glsc.ngateway.common.api.ldap.resp.AppEhrResponse;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.User;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.outsys.*;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.task.TaskInfo;
import com.glsc.ngateway.common.base.repo.mysql.opmanagemain.outsys.*;
import com.glsc.ngateway.opmanage.dto.OutSystemUserDto;
import com.glsc.ngateway.opmanage.enums.OutSystemFirstLevelEnum;
import com.glsc.ngateway.opmanage.dto.OaBatchUploadFileDto;
import com.glsc.ngateway.opmanage.dto.OutSystemExcelDto;
import com.glsc.ngateway.opmanage.enums.TaskTypeUrlEnum;
import com.glsc.ngateway.opmanage.service.MailService;
import com.glsc.ngateway.opmanage.service.SystemConfigService;
import com.glsc.ngateway.opmanage.service.UserService;
import com.glsc.ngateway.opmanage.service.feign.GatewayFeignService;
import com.glsc.ngateway.opmanage.service.task.TaskInfoService;
import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.opmanage.utils.report.ReportFileUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportUploadContext;
import com.google.common.collect.Lists;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OutSystemService {


    @Resource
    private OutSystemAuthInfoRepository outSystemAuthInfoRepository;

    @Resource
    private OutSystemDeptInfoRepository deptInfoRepository;

    @Resource
    private OutSystemInfoRepository systemInfoRepository;

    @Resource
    private OutSystemUserRepository userRepository;

    @Resource
    private GatewayFeignService gatewayFeignService;

    @Resource
    private IFeignLdapService feignLdapService; // feignLdap

    @Resource
    private MailService mailService;

    @Resource
    private SystemConfigService systemConfigService;

    @Resource
    private UserService userService;

    @Resource
    private OutSystemTemplateService templateService;

    @Resource
    private OutSystemTemplateRelService relService;

    @Resource
    private OutSystemTemplateItemService templateItemService;

    @Resource
    private OutSystemAuthTemplateService authTemplateService;

    @Resource
    private OutSystemOaLogRepository outSystemOaLogRepository;

    @Resource
    private TaskInfoService taskInfoService;


    /**
     * 分页查询外部系统权限信息
     *
     * @param pageNo
     * @param pageSize
     * @param param
     * @return
     */
    public Page<OutSystemAuthInfo> page(int pageNo, int pageSize, Map<String, Object> param) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "createTime";

        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        Page<OutSystemAuthInfo> page = outSystemAuthInfoRepository.findAll(SpecificationUtil.buildSpecification(param, OutSystemAuthInfo.class), pageable);
        return page;
    }

    /**
     * 根据id查找外部系统信息
     *
     * @param id
     * @return
     */
    public OutSystemAuthInfo findById(Integer id) {
        Optional<OutSystemAuthInfo> optional = outSystemAuthInfoRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        }
        return null;
    }

    /**
     * 保存外部系统权限信息
     *
     * @param outSystemAuthInfo
     * @return
     */
    public OutSystemAuthInfo save(OutSystemAuthInfo outSystemAuthInfo) {
        //不支持权限名称为空字符串
        outSystemAuthInfo.setAuthName1(StringUtils.isBlank(outSystemAuthInfo.getAuthName1()) ? null : outSystemAuthInfo.getAuthName1().trim());
        outSystemAuthInfo.setAuthName2(StringUtils.isBlank(outSystemAuthInfo.getAuthName2()) ? null : outSystemAuthInfo.getAuthName2().trim());
        outSystemAuthInfo.setAuthName3(StringUtils.isBlank(outSystemAuthInfo.getAuthName3()) ? null : outSystemAuthInfo.getAuthName3().trim());
        outSystemAuthInfo.setAuthName4(StringUtils.isBlank(outSystemAuthInfo.getAuthName4()) ? null : outSystemAuthInfo.getAuthName4().trim());
        outSystemAuthInfo.setAuthName5(StringUtils.isBlank(outSystemAuthInfo.getAuthName5()) ? null : outSystemAuthInfo.getAuthName5().trim());

        Assert.isTrue(StringUtils.isNotBlank(outSystemAuthInfo.getDeptName()), "部门名称不可为空");

        List<OutSystemDeptInfo> depts = deptInfoRepository.findAll(Example.of(OutSystemDeptInfo.builder().enableFlag("Y").deptName(outSystemAuthInfo.getDeptName()).build()));
        if (CollectionUtil.isEmpty(depts)) {
            //未查询到部门则保存部门信息
            if (StringUtils.isNotBlank(outSystemAuthInfo.getDeptName())) {
                OutSystemDeptInfo saveDept = saveOutSystemDeptInfo(OutSystemDeptInfo.builder().enableFlag("Y").deptName(outSystemAuthInfo.getDeptName()).build());
                outSystemAuthInfo.setDeptId(saveDept.getId());
            }
        } else {
            outSystemAuthInfo.setDeptId(depts.get(0).getId());
        }

        List<OutSystemInfo> systemInfoList = systemInfoRepository.findAll(Example.of(OutSystemInfo.builder().enableFlag("Y").sysName(outSystemAuthInfo.getSystemName()).build()));
        if (CollectionUtil.isEmpty(systemInfoList)) {
            //未查询到部门则保存系统信息
            OutSystemInfo saveSys = systemInfoRepository.save(OutSystemInfo.builder().enableFlag("Y").sysName(outSystemAuthInfo.getSystemName()).build());
            outSystemAuthInfo.setSysId(saveSys.getId());
        } else {
            outSystemAuthInfo.setSysId(systemInfoList.get(0).getId());
        }

        List<OutSystemUserInfo> userList = userRepository.findAll(Example.of(OutSystemUserInfo.builder().enableFlag("Y").operatorName(outSystemAuthInfo.getOperatorName()).build()));
        if (CollectionUtil.isEmpty(userList)) {
            //未查询到部门则保存系统信息
            OutSystemUserInfo saveUser = userRepository.save(OutSystemUserInfo.builder().deptId(outSystemAuthInfo.getDeptId()).enableFlag("Y").operatorName(outSystemAuthInfo.getOperatorName()).build());
            outSystemAuthInfo.setUserId(saveUser.getId());
        } else {
            outSystemAuthInfo.setUserId(userList.get(0).getId());
        }

        return outSystemAuthInfoRepository.save(outSystemAuthInfo);
    }

    /**
     * 从模板创建用户
     *
     * @param dto
     */
    public void saveFromTemplate(OutSystemUserDto dto) {
        User user = userService.findByUserAccount(dto.getUserOaAccount());
        OutSystemTemplate template = templateService.findById(dto.getTemplateId());
        List<OutSystemTemplateRel> systemList = relService.findByTemplateId(dto.getTemplateId(), null);

        if (CollectionUtil.isEmpty(dto.getCheckIdList())) {
            return;
        }

        if (CollectionUtil.isNotEmpty(systemList)) {
            for (OutSystemTemplateRel rel : systemList) {

                if (dto.getCheckIdList().contains(rel.getSysId())) {
                    List<OutSystemAuthInfo> authInfoList = Lists.newArrayList();
                    List<OutSystemTemplateItem> items = templateItemService.listByTemplateIdAndSysId(rel.getTemplateId(), rel.getSysId());
                    if (CollectionUtil.isNotEmpty(items)) {

                        items = items.stream().filter(e -> "Y".equals(e.getStatus())).collect(Collectors.toList());

                        List<OutSystemAuthTemplate> authList = authTemplateService.findByIds(items.stream().map(OutSystemTemplateItem::getAuthId).collect(Collectors.toList()));
                        Map<Integer, OutSystemAuthTemplate> authMap = authList.stream().collect(Collectors.toMap(OutSystemAuthTemplate::getId, e -> e, (i, j) -> j));

                        for (OutSystemTemplateItem item : items) {
                            OutSystemAuthTemplate authTemplate = authMap.get(item.getAuthId());
                            authInfoList.add(OutSystemAuthInfo.builder().authName1(authTemplate.getAuthName1()).authName2(authTemplate.getAuthName2())
                                    .authName3(authTemplate.getAuthName3()).authName4(authTemplate.getAuthName4()).authName5(authTemplate.getAuthName5())
                                    .deleted("N").deptName(dto.getDeptName()).postName(dto.getPostName()).enable("Y").operatorName(user.getName()).build());
                        }
                    }
                    OutSystemInfo system = findSystemById(rel.getSysId());
                    addAll(authInfoList, system.getSysName());
                }

            }
        }
    }


    /**
     * 根据id删除记录
     *
     * @param id
     */
    public void deleteById(Integer id) {
        OutSystemAuthInfo outSystemAuthInfo = findById(id);
        Assert.isTrue(Objects.nonNull(outSystemAuthInfo), "未找到删除的对象");
        outSystemAuthInfo.setDeleted("Y");
        outSystemAuthInfoRepository.save(outSystemAuthInfo);
    }

    /**
     * 根据id批量删除
     *
     * @param ids
     */
    public void deleteByIds(List<Integer> ids) {
        Assert.isTrue(CollectionUtil.isNotEmpty(ids), "请选择要删除的数据");
        List<OutSystemAuthInfo> list = outSystemAuthInfoRepository.findAllById(ids);
        if (CollectionUtil.isNotEmpty(list)) {
            for (OutSystemAuthInfo outSystemAuthInfo : list) {
                outSystemAuthInfo.setDeleted("Y");
            }
        }
        outSystemAuthInfoRepository.saveAll(list);
    }


    /**
     * 启用禁用
     *
     * @param id
     * @param enable N 禁用 Y启用
     */
    public OutSystemAuthInfo enable(Integer id, String enable) {
        OutSystemAuthInfo outSystemAuthInfo = findById(id);
        Assert.isTrue(Objects.nonNull(outSystemAuthInfo), "未找到操作对象");
        outSystemAuthInfo.setEnable(enable);
        return outSystemAuthInfoRepository.save(outSystemAuthInfo);
    }


    /**
     * 导入滴干活
     *
     * @param file
     * @param systemName
     * @return
     * @throws IOException
     */
    @Transactional
    public ReportUploadContext<OutSystemExcelDto, String> ousSystemImport(MultipartFile file, String systemName) throws IOException {
        ReportUploadContext<OutSystemExcelDto, String> context = ReportUploadContext.<OutSystemExcelDto, String>builder()
                .config(ReportFileConfigEnum.OUT_SYSTEM_EXPORT)
                .file(file)
                .build();

        ReportFileUtil.readSingleExcel(context);
        Assert.notEmpty(context.getReadRes(), "上传内容不可为空");

        List<OutSystemAuthInfo> authInfoList = Lists.newArrayList();

        List<OutSystemExcelDto> readResList = context.getReadRes();

        for (OutSystemExcelDto outSystemExcelDto : readResList) {
            authInfoList.add(convertDto(outSystemExcelDto, systemName));
        }

        addAll(authInfoList, systemName);
        return context;
    }


    public void addAll(List<OutSystemAuthInfo> authInfoList, String systemName) {
        //部门信息不多，所以能findAll,多的话需要分页
        List<OutSystemDeptInfo> deptList = deptInfoRepository.findAll();
        if (CollectionUtil.isEmpty(deptList)) {
            deptList = Lists.newArrayList();
        }
        OutSystemInfo systemInfo = null;
        List<OutSystemInfo> sysList = systemInfoRepository.findAll(Example.of(OutSystemInfo.builder().sysName(systemName).enableFlag("Y").build()));
        if (CollectionUtil.isEmpty(sysList)) {
            OutSystemInfo saveSys = systemInfoRepository.save(OutSystemInfo.builder().enableFlag("Y").sysName(systemName).build());
            systemInfo = saveSys;
        } else {
            systemInfo = sysList.get(0);
        }

        List<OutSystemUserInfo> userList = userRepository.findAll(Example.of(OutSystemUserInfo.builder().enableFlag("Y").build()));
        if (CollectionUtil.isEmpty(userList)) {
            userList = Lists.newArrayList();
        }

        List<OutSystemAuthInfo> addList = Lists.newArrayList();
        for (OutSystemAuthInfo outSystemAuthInfo : authInfoList) {

            if (StringUtils.isBlank(outSystemAuthInfo.getOperatorName())) {
                continue;
            }
            outSystemAuthInfo.setSysId(systemInfo.getId());
            outSystemAuthInfo.setSystemName(systemInfo.getSysName());

            addList.add(outSystemAuthInfo);

            List<OutSystemDeptInfo> thisDept = deptList.stream().filter(e -> e.getDeptName().equals(outSystemAuthInfo.getDeptName())).collect(Collectors.toList());
            if (CollectionUtil.isEmpty(thisDept)) {
                if (StringUtils.isNotBlank(outSystemAuthInfo.getDeptName())) {
                    OutSystemDeptInfo saveDept = saveOutSystemDeptInfo(OutSystemDeptInfo.builder().deptName(outSystemAuthInfo.getDeptName()).enableFlag("Y").build());
                    outSystemAuthInfo.setDeptId(saveDept.getId());
                    deptList.add(saveDept);
                }
            } else {
                outSystemAuthInfo.setDeptId(thisDept.get(0).getId());
            }

            List<OutSystemUserInfo> thisUser = userList.stream().filter(e ->
                    (e.getOperatorName().equals(outSystemAuthInfo.getOperatorName()))).collect(Collectors.toList());
            if (CollectionUtil.isEmpty(thisUser)) {
                //未查询到部门则保存系统信息
                OutSystemUserInfo saveUser = userRepository.save(OutSystemUserInfo.builder()
                        .deptId(outSystemAuthInfo.getDeptId()).enableFlag("Y").operatorName(outSystemAuthInfo.getOperatorName()).build());
                outSystemAuthInfo.setUserId(saveUser.getId());
                userList.add(saveUser);
            } else {
                outSystemAuthInfo.setUserId(thisUser.get(0).getId());
            }
        }
        outSystemAuthInfoRepository.saveAll(addList);
    }

    /**
     * 根据用户名和系统名更新用户的权限信息,旧的信息逻辑删除
     *
     * @param dataList
     * @param systemName
     */
    @Transactional
    public void dealUserAuth(List<OutSystemExcelDto> dataList, String systemName) {
        if (CollectionUtil.isEmpty(dataList)) {
            return;
        }
        Map<String, List<OutSystemExcelDto>> operatorNameDataListMap = dataList.stream().collect(Collectors.groupingBy(OutSystemExcelDto::getOperatorName));
        for (String operatorName : operatorNameDataListMap.keySet()) {
            if (StringUtils.isNotBlank(operatorName)) {
                List<OutSystemAuthInfo> operatorDataList = findByOperatorName(operatorName, systemName);
                if (CollectionUtil.isNotEmpty(operatorDataList)) {
                    operatorDataList.forEach(e -> e.setDeleted("Y"));
                }
                outSystemAuthInfoRepository.saveAll(operatorDataList);

                List<OutSystemExcelDto> outSystemExcelDtoList = operatorNameDataListMap.get(operatorName);
                if (CollectionUtil.isNotEmpty(outSystemExcelDtoList)) {
                    List<OutSystemAuthInfo> saveList = Lists.newArrayList();
                    for (OutSystemExcelDto outSystemExcelDto : outSystemExcelDtoList) {
                        saveList.add(convertDto(outSystemExcelDto, systemName));
                    }
                    if (CollectionUtil.isNotEmpty(saveList)) {
                        outSystemAuthInfoRepository.saveAll(saveList);
                    }
                }
            }
        }
    }

    /**
     * 根据用户名称和系统名称删除用户的所有权限信息
     *
     * @param operatorName
     * @param systemName
     */
    public void deleteAllAuthByOperatorName(String operatorName, String systemName) {
        List<OutSystemAuthInfo> operatorDataList = findByOperatorName(operatorName, systemName);
        if (CollectionUtil.isNotEmpty(operatorDataList)) {
            operatorDataList.forEach(e -> e.setDeleted("Y"));
        }
        outSystemAuthInfoRepository.saveAll(operatorDataList);
    }

    /**
     * 根据名称查找所有外部系统权限信息
     *
     * @param operatorName
     * @return
     */
    public List<OutSystemAuthInfo> findByOperatorName(String operatorName, String systemName) {
        return outSystemAuthInfoRepository.findAll(Example.of(OutSystemAuthInfo.builder().operatorName(operatorName).systemName(systemName).build()));
    }


    private OutSystemAuthInfo convertDto(OutSystemExcelDto dto, String systemName) {
        OutSystemAuthInfo outSystemAuthInfo = OutSystemAuthInfo.builder().systemName(systemName).authName1(dto.getAuthName1()).deleted("N").enable("Y")
                .operatorName(dto.getOperatorName()).deptName(dto.getDeptName()).postName(dto.getPostName())
                .userName(dto.getUserName()).userAccount(dto.getUserAccount()).build();
        if (StringUtils.isNotBlank(dto.getAuthName2())) {
            outSystemAuthInfo.setAuthName2(dto.getAuthName2());
        }
        if (StringUtils.isNotBlank(dto.getAuthName3())) {
            outSystemAuthInfo.setAuthName3(dto.getAuthName3());
        }
        if (StringUtils.isNotBlank(dto.getAuthName4())) {
            outSystemAuthInfo.setAuthName4(dto.getAuthName4());
        }
        if (StringUtils.isNotBlank(dto.getAuthName5())) {
            outSystemAuthInfo.setAuthName5(dto.getAuthName5());
        }

        return outSystemAuthInfo;
    }


    /**
     * 定时任务触发-按照部门创建64.系统平台账号权限定期确认流程
     */
    @XxlJob("outSystemService_createOaFlow")
    public void createOaFlow() {
        //按照部门创建53.信息系统业务类账号、权限审核流程

        List<OutSystemDeptInfo> deptList = deptInfoRepository.findAll(Example.of(OutSystemDeptInfo.builder().oaFlag("Y").build()));
        if (CollectionUtil.isEmpty(deptList)) {
            return;
        }
        String thisMonth = DateUtil.today().substring(0, 7);
        log.info("权限确认流程定时任务-查询出的部门信息：{}", JSON.toJSONString(deptList));
        for (OutSystemDeptInfo deptInfo : deptList) {

            String title = "64.系统平台账号权限定期确认流程-" + deptInfo.getDeptName() + "-" + DateUtil.today();
            OutSystemOaLog oaLog = OutSystemOaLog.builder().build();
            oaLog.setDeptName(deptInfo.getDeptName());
            oaLog.setDeptId(deptInfo.getId());
            oaLog.setStatus("N");
            oaLog.setExecuteDay(thisMonth);
            oaLog.setOaFlowName(title);




            /*LdapEhrEmpDto creatorInfo = getOaCreatorInfo(deptInfo.getOaCreatorId());
            if (Objects.isNull(creatorInfo)) {
                oaLog.setMemo("oa触发失败,未查询到oa创建者信息");
                outSystemOaLogRepository.save(oaLog);
                continue;
            }else {
                if (!deptInfo.getOaDeptId().equals(creatorInfo.getOaDeptId()+"")) {
                    oaLog.setMemo("oa触发失败,oa创建者部门变更");
                    outSystemOaLogRepository.save(oaLog);
                    continue;
                }
            }*/


            //检查是否今日成功执行过
            List<OutSystemOaLog> outSystemOaLogs = outSystemOaLogRepository.findAll(Example.of(OutSystemOaLog.builder().deptId(deptInfo.getId()).executeDay(thisMonth).build()));
            log.info("权限确认流程定时任务-查询出的执行记录：部门{}，今日执行记录{}", JSON.toJSONString(deptInfo), JSON.toJSONString(outSystemOaLogs));
            if (CollectionUtil.isNotEmpty(outSystemOaLogs)) {
                continue;
            }

            try {
                List<OutSystemAuthInfo> authInfoList = outSystemAuthInfoRepository.findAll(Example.of(OutSystemAuthInfo.builder().enable("Y").deptId(deptInfo.getId()).build()));
                log.info("权限确认流程定时任务-查询出的执行记录：部门{}，查询出的权限列表{}", JSON.toJSONString(deptInfo), JSON.toJSONString(authInfoList));
                if (CollectionUtil.isEmpty(authInfoList)) {
                    continue;
                }
                //按照系统对权限进行分组，每个系统单独生成一个excel
                List<File> attachmentList = Lists.newArrayList();
                Map<Integer, List<OutSystemAuthInfo>> sysAndAuthMap = authInfoList.stream().collect(Collectors.groupingBy(OutSystemAuthInfo::getSysId));

                for (Integer sysId : sysAndAuthMap.keySet()) {

                    List<OutSystemAuthInfo> outSystemAuthInfoList = sysAndAuthMap.get(sysId);
                    if (CollectionUtil.isNotEmpty(outSystemAuthInfoList)) {

                        Optional<OutSystemInfo> outSystemInfoOptional = systemInfoRepository.findById(sysId);
                        OutSystemInfo outSystemInfo = outSystemInfoOptional.get();
                        //仅为启用状态下的系统生成excel
                        if (outSystemInfo.getEnableFlag().equals("Y")) {
                            //生成导出excel
                            List<OutSystemExcelDto> outSystemExcelDtos = convertOutSystemExcelDto(outSystemAuthInfoList);
                            attachmentList.add(createEmailFile(outSystemInfo.getSysName() + ".xlsx", ReportFileConfigEnum.OUT_SYSTEM_EXPORT, outSystemExcelDtos));
                        }
                    }
                }

                List<OaBatchUploadFileDto> oaUploadFileList = Lists.newArrayList();
                if (CollectionUtil.isEmpty(attachmentList)) {
                    continue;
                }
                //上传附件到oa
                for (File file : attachmentList) {
                    OaBatchUploadFileDto oaBatchUploadFileDto = gatewayFeignService.uploadOaFileAndReturnPath(file);
                    oaUploadFileList.add(oaBatchUploadFileDto);
                }

                Map<String, Object> dataMap = new HashMap<>();


                dataMap.put("creater", deptInfo.getOaCreatorId());//创建人
                dataMap.put("title", title);//流程标题
                dataMap.put("applyDate", DateUtil.today());//申请日期
                dataMap.put("applicant", deptInfo.getOaCreatorId());//申请人
                dataMap.put("applicantDepart", deptInfo.getOaDeptId());//申请人部门
                dataMap.put("applicantComp", deptInfo.getOaCompId());//申请人公司
                dataMap.put("category", "0");//类别，紧急程度

                LocalDate currentDate = LocalDate.now();

                // 计算几天后的日期
                int daysToAdd = 7; // 假设要计算7天后的日期
                LocalDate newDate = currentDate.plusDays(daysToAdd);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

                String formattedDate = newDate.format(formatter);

                dataMap.put("xwwcsj", formattedDate);//希望完成时间

                //设置oa流程的附件参数
                if (CollectionUtil.isNotEmpty(oaUploadFileList)) {
                    Map<String, Object> fileDataMap = new HashMap<>();
                    fileDataMap.put("annexId", StringUtils.join(oaUploadFileList.stream().map(OaBatchUploadFileDto::getAnnexId).collect(Collectors.toList()), ","));
                    fileDataMap.put("annexName", StringUtils.join(oaUploadFileList.stream().map(OaBatchUploadFileDto::getAnnexName).collect(Collectors.toList()), ","));

                    dataMap.put("fj", fileDataMap);//OA附件字段，多个附件ID英文逗号拼接的字符串
                }

                String workFlowId = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_SYSTEM_TEC_WORK_FLOW_ID);
                String oaFlowResp = gatewayFeignService.createOaFlowWithDeptId(dataMap, workFlowId);
                log.info("权限确认流程定时任务-查询出的执行记录：部门{}，oa响应{}", JSON.toJSONString(deptInfo), oaFlowResp);


                //更新deptInfo的oaflowid  {"code":0,"data":{"msg":"","requestid":"922892"},"status":"SUCCESS"}
                JSONObject response = JSON.parseObject(oaFlowResp);
                if (StringUtils.isNotBlank(response.getString("code")) && "0".equals(response.getString("code"))) {
                    if (StringUtils.isNotBlank(response.getString("data"))) {
                        deptInfo.setOaFlowId(JSON.parseObject(response.getString("data")).getString("requestid"));
                        saveOutSystemDeptInfo(deptInfo);
                        oaLog.setStatus("Y");
                        oaLog.setOaFlowId(JSON.parseObject(response.getString("data")).getString("requestid"));
                    }
                }
                outSystemOaLogRepository.save(oaLog);
            } catch (Exception e) {
                log.error("定时任务触发-按照部门创建64.系统平台账号权限定期确认流程异常", e);
                oaLog.setDeptName(deptInfo.getDeptName());
                oaLog.setDeptId(deptInfo.getId());
                oaLog.setStatus("N");
                oaLog.setOaFlowName(title);
                oaLog.setExecuteDay(thisMonth);
                oaLog.setMemo("流程触发过程中发生异常，请检查日志");
                outSystemOaLogRepository.save(oaLog);

                OutSystemService.log.error("定时任务触发-按照部门创建64.系统平台账号权限定期确认流程异常", e);
                mailService.sendMailToAdmin("外部系统权限oa流程触发失败", Arrays.toString(e.getStackTrace()));
            }
        }
    }

    /**
     * 重新触发一个oa信息
     *
     * @param id
     */
    public OutSystemOaLog retry(Integer id) {
        Optional<OutSystemOaLog> optional = outSystemOaLogRepository.findById(id);
        OutSystemOaLog systemOaLog = optional.get();
        if (Objects.isNull(systemOaLog)) {
            return null;
        }

        Optional<OutSystemDeptInfo> deptInfoOptional = deptInfoRepository.findById(systemOaLog.getDeptId());
        OutSystemDeptInfo deptInfo = deptInfoOptional.get();
        if (Objects.isNull(deptInfo)) {
            return null;
        }

        Assert.isTrue("N".equals(systemOaLog.getStatus()), "只有失败状态下才可以重新触发oa");

        try {
            List<OutSystemAuthInfo> authInfoList = outSystemAuthInfoRepository.findAll(Example.of(OutSystemAuthInfo.builder().enable("Y").deptId(deptInfo.getId()).build()));
            if (CollectionUtil.isEmpty(authInfoList)) {
                return null;
            }
            //按照系统对权限进行分组，每个系统单独生成一个excel
            List<File> attachmentList = Lists.newArrayList();
            Map<Integer, List<OutSystemAuthInfo>> sysAndAuthMap = authInfoList.stream().collect(Collectors.groupingBy(OutSystemAuthInfo::getSysId));

            for (Integer sysId : sysAndAuthMap.keySet()) {

                List<OutSystemAuthInfo> outSystemAuthInfoList = sysAndAuthMap.get(sysId);
                if (CollectionUtil.isNotEmpty(outSystemAuthInfoList)) {

                    Optional<OutSystemInfo> outSystemInfoOptional = systemInfoRepository.findById(sysId);
                    OutSystemInfo outSystemInfo = outSystemInfoOptional.get();
                    //仅为启用状态下的系统生成excel
                    if (outSystemInfo.getEnableFlag().equals("Y")) {
                        //生成导出excel
                        List<OutSystemExcelDto> outSystemExcelDtos = convertOutSystemExcelDto(outSystemAuthInfoList);
                        attachmentList.add(createEmailFile(outSystemInfo.getSysName() + ".xlsx", ReportFileConfigEnum.OUT_SYSTEM_EXPORT, outSystemExcelDtos));
                    }
                }
            }

            List<OaBatchUploadFileDto> oaUploadFileList = Lists.newArrayList();
            if (CollectionUtil.isNotEmpty(attachmentList)) {
                //上传附件到oa
                for (File file : attachmentList) {
                    OaBatchUploadFileDto oaBatchUploadFileDto = gatewayFeignService.uploadOaFileAndReturnPath(file);
                    oaUploadFileList.add(oaBatchUploadFileDto);
                }
            }

            Map<String, Object> dataMap = new HashMap<>();

            String title = "64.系统平台账号权限定期确认流程-" + deptInfo.getDeptName() + "-" + DateUtil.today();
            dataMap.put("creater", deptInfo.getOaCreatorId());//创建人
            dataMap.put("title", title);//流程标题
            dataMap.put("applyDate", DateUtil.today());//申请日期
            dataMap.put("applicant", deptInfo.getOaCreatorId());//申请人
            dataMap.put("applicantDepart", deptInfo.getOaDeptId());//申请人部门
            dataMap.put("applicantComp", deptInfo.getOaCompId());//申请人公司
            dataMap.put("category", "0");//类别，紧急程度

            systemOaLog.setOaFlowName(title);

            //设置oa流程的附件参数
            if (CollectionUtil.isNotEmpty(oaUploadFileList)) {
                Map<String, Object> fileDataMap = new HashMap<>();
                fileDataMap.put("annexId", StringUtils.join(oaUploadFileList.stream().map(OaBatchUploadFileDto::getAnnexId).collect(Collectors.toList()), ","));
                fileDataMap.put("annexName", StringUtils.join(oaUploadFileList.stream().map(OaBatchUploadFileDto::getAnnexName).collect(Collectors.toList()), ","));

                dataMap.put("fj", fileDataMap);//OA附件字段，多个附件ID英文逗号拼接的字符串
            }

            String workFlowId = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_SYSTEM_TEC_WORK_FLOW_ID);
            String oaFlowResp = gatewayFeignService.createOaFlow(dataMap, workFlowId);

            //更新deptInfo的oaflowid  {"code":0,"data":{"msg":"","requestid":"922892"},"status":"SUCCESS"}
            JSONObject response = JSON.parseObject(oaFlowResp);
            if (StringUtils.isNotBlank(response.getString("code")) && "0".equals(response.getString("code"))) {
                if (StringUtils.isNotBlank(response.getString("data"))) {
                    deptInfo.setOaFlowId(JSON.parseObject(response.getString("data")).getString("requestid"));
                    saveOutSystemDeptInfo(deptInfo);
                    systemOaLog.setStatus("Y");
                    systemOaLog.setOaFlowId(JSON.parseObject(response.getString("data")).getString("requestid"));
                }
            }
            outSystemOaLogRepository.save(systemOaLog);
            return systemOaLog;
        } catch (Exception e) {
            OutSystemService.log.error("定时任务触发-按照部门创建64.系统平台账号权限定期确认流程异常", e);
            mailService.sendMailToAdmin("外部系统权限oa流程触发失败", Arrays.toString(e.getStackTrace()));
        }
        return null;
    }


    private File createEmailFile(String fileName, ReportFileConfigEnum type, Object datas) {
        FileOutputStream fos = null;
        File file = new File(fileName);
        try {
            fos = new FileOutputStream(file);
            byte[] export = ReportFileUtil.export(datas, type);
            fos.write(export);
        } catch (Exception e) {
            log.error("创建外部系统权限邮件附件异常", e);
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                log.error("创建外部系统权限邮件附件关闭流异常", e);
            }
        }
        return file;
    }


    private List<OutSystemExcelDto> convertOutSystemExcelDto(List<OutSystemAuthInfo> list) {
        List<OutSystemExcelDto> resList = Lists.newArrayList();
        if (CollectionUtil.isEmpty(list)) {
            return resList;
        }

        for (OutSystemAuthInfo outSystemAuthInfo : list) {
            resList.add(OutSystemExcelDto.builder().systemName(outSystemAuthInfo.getSystemName()).authName1(outSystemAuthInfo.getAuthName1()).authName2(outSystemAuthInfo.getAuthName2()).authName3(outSystemAuthInfo.getAuthName3()).
                    authName4(outSystemAuthInfo.getAuthName4()).authName5(outSystemAuthInfo.getAuthName5()).deptName(outSystemAuthInfo.getDeptName()).
                    postName(outSystemAuthInfo.getPostName()).operatorName(outSystemAuthInfo.getOperatorName()).userName(outSystemAuthInfo.getUserName()).userAccount(outSystemAuthInfo.getUserAccount()).build());
        }
        return resList;
    }

    /**
     * @return
     */
    public OutSystemInfo findSystemById(Integer id) {
        if (Objects.isNull(id)) {
            return null;
        }
        Optional<OutSystemInfo> optional = systemInfoRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        }
        return null;
    }

    public List<OutSystemInfo> listAllUseFullSystem() {
        return systemInfoRepository.findAll();
    }

    /**
     * 获取oa创建者的信息
     *
     * @param username
     * @return
     */
    public LdapEhrEmpDto getOaCreatorInfo(String username) {
        if (StringUtils.isBlank(username)) {
            return null;
        }
        AppEhrResponse<LdapEhrEmpDto> res = feignLdapService.getLdapEhrEmp(username, null, false);
        if (res != null) {
            if (res.getStatus() == 0) {
                LdapEhrEmpDto emp = res.getData();
                return emp;
            }
        }
        return null;
    }

    /**
     * 保存部门信息
     * 注意！！！保存部门信息请都调用此接口
     *
     * @return
     */
    public OutSystemDeptInfo saveOutSystemDeptInfo(OutSystemDeptInfo deptInfo) {

        if (Objects.isNull(deptInfo.getId())) {
            TaskInfo task = new TaskInfo();
            task.setType(TaskTypeUrlEnum.OUT_SYSTEM_DEPT_ADD.getType());
            task.setRoleCode(TaskTypeUrlEnum.OUT_SYSTEM_DEPT_ADD.getRoleCode());
            task.setName("[外部系统权限部门新增]-" + deptInfo.getDeptName());
            task.setCreateTime(new Date());
            task.setStatus("0");
            taskInfoService.saveTaskInfo(task);
        }

        return deptInfoRepository.save(deptInfo);
    }


}
